from pathlib import Path
from typing import List, Optional
from uuid import UUID

from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from crud.bid_document_crud import BidDocumentCRUD
from crud.tender_crud import TenderCRUD
from crud.tender_document_crud import TenderDocumentCRUD
from .consolidators.pipe_fitting.consolidator import Consolidator, Bidder
from .consolidators.sea_transportation import SeaTransportationMerger, BidderFile
from .consolidators.electrical.consolidator import Consolidator as ElectricalConsolidator
from .consolidators.steel.consolidator import Consolidator as SteelConsolidator
from .file_manager import FileManager


class SummaryFile(BaseModel):
    name: str
    file_path: str


class SummaryService:
    def __init__(self, db: AsyncSession):
        self.tender_crud = TenderCRUD(db)
        self.tender_document_crud = TenderDocumentCRUD(db)
        self.bid_document_crud = BidDocumentCRUD(db)

    async def create_summary(self, tender_id: UUID) -> str:
        tender = await self.tender_crud.get_by_id(tender_id)
        tender_doc = await self.tender_document_crud.get_by_tender_id(tender_id)
        bid_docs = await self.bid_document_crud.get_by_tender_id(tender_id)
        merger = SeaTransportationMerger(Path(tender_doc.file_path))
        bidder_files: List[BidderFile] = []
        for bid_doc in bid_docs:
            file_path = Path(bid_doc.file_path)
            if file_path.exists():
                bidder_files.append(
                    BidderFile(
                        file_path=file_path,
                        name=bid_doc.name,
                        bargaining=bid_doc.bargaining,
                    )
                )

        manager = FileManager(tender.category, tender.quarter)
        summary_file_path = manager.create_summary_file_path()
        merger.merge(bidder_files, summary_file_path)
        summary_file = SummaryFile(
            name=f"{tender.quarter}{tender.category}汇总文件.xlsx",
            file_path=str(summary_file_path),
        )
        return summary_file

    async def get_summary(self, tender_id: UUID) -> SummaryFile | None:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(tender.category, tender.quarter)

        summary_file: Path | None = manager.get_summary_document_file()
        if not summary_file:
            return None
        else:
            summary = SummaryFile(
                name=f"{tender.quarter}{tender.category}汇总文件.xlsx",
                file_path=str(summary_file),
            )
            return summary

    async def create_summary_for_pipe_fitting(self, tender_id: UUID) -> str:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(str(tender.category), str(tender.quarter))
        tender_file: Path = manager.path / "tender.xlsx"
        summary_file: Path = manager.path / "summary.xlsx"

        # 遍历文件系统，按供应商名分组
        bid_files = manager.list_bid_document_files()
        bidders_dict = {}
        for file_path in bid_files:
            name = file_path.stem
            if name.endswith(".bargaining"):
                supplier = name[: -len(".bargaining")]
                if supplier not in bidders_dict:
                    bidders_dict[supplier] = {
                        "document": None,
                        "bargaining_document": None,
                    }
                bidders_dict[supplier]["bargaining_document"] = file_path
            else:
                supplier = name
                if supplier not in bidders_dict:
                    bidders_dict[supplier] = {
                        "document": None,
                        "bargaining_document": None,
                    }
                bidders_dict[supplier]["document"] = file_path

        bidders = []
        for name, files in bidders_dict.items():
            if files["document"] is not None:
                bidders.append(
                    Bidder(
                        name=name,
                        document=files["document"],
                        has_bargaining=files["bargaining_document"] is not None,
                        bargaining_document=files["bargaining_document"],
                    )
                )

        consolidator = Consolidator(tender_file, summary_file)
        consolidator.load_tender()
        try:
            consolidator.add_bids(bidders)
        except Exception as e:
            raise e
        consolidator.save()
        supplier_names = [b.name for b in bidders]
        return f"已汇总完成，共计{len(supplier_names)}个供应商：{','.join(supplier_names)}。 + error info"

    async def get_summary_for_pipe_fitting(
        self, tender_id: UUID
    ) -> Optional[SummaryFile]:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(str(tender.category), str(tender.quarter))
        summary_file: Path = manager.path / "summary.xlsx"
        if not summary_file.exists():
            return None
        return SummaryFile(
            name=f"{tender.quarter}{tender.category}汇总表.xlsx",
            file_path=str(summary_file),
        )

    async def get_summary_for_steel(self, tender_id: UUID) -> Optional[SummaryFile]:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(tender.category, tender.quarter)
        summary_file: Path | None = manager.get_summary_document_file()
        if not summary_file:
            return None
        return SummaryFile(
            name=f"{tender.quarter}{tender.category}汇总文件.xlsx",
            file_path=str(summary_file),
        )

    async def create_summary_for_steel(self, tender_id: UUID) -> str:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(tender.category, tender.quarter)
        tender_file: Path | None = manager.path / "tender.xlsx"
        if not tender_file:
            raise FileNotFoundError("招标文件不存在")
        summary_file: Path = manager.create_summary_file_path()

        # 遍历文件系统，按供应商名分组
        bid_files = manager.list_bid_document_files()
        bidders_dict = {}
        for file_path in bid_files:
            name = file_path.stem
            if name.endswith(".bargaining"):
                supplier = name[: -len(".bargaining")]
                if supplier not in bidders_dict:
                    bidders_dict[supplier] = {
                        "document": None,
                        "bargaining_document": None,
                    }
                bidders_dict[supplier]["bargaining_document"] = file_path
            else:
                supplier = name
                if supplier not in bidders_dict:
                    bidders_dict[supplier] = {
                        "document": None,
                        "bargaining_document": None,
                    }
                bidders_dict[supplier]["document"] = file_path

        bidders = []
        for name, files in bidders_dict.items():
            if files["document"] is not None:
                bidders.append(
                    Bidder(
                        name=name,
                        document=files["document"],
                        has_bargaining=files["bargaining_document"] is not None,
                        bargaining_document=files["bargaining_document"],
                    )
                )

        consolidator = SteelConsolidator(tender_file, summary_file)
        consolidator.load_tender()
        try:
            consolidator.add_bids(bidders)
        except Exception as e:
            raise e
        consolidator.save()
        supplier_names = [b.name for b in bidders]
        return f"已汇总完成，共计{len(supplier_names)}个供应商：{','.join(supplier_names)}。 + error info"

    async def get_summary_for_electrical(
        self, tender_id: UUID
    ) -> Optional[SummaryFile]:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(tender.category, tender.quarter)
        summary_file: Path | None = manager.get_summary_document_file()
        if not summary_file:
            return None
        return SummaryFile(
            name=f"{tender.quarter}{tender.category}汇总文件.xlsx",
            file_path=str(summary_file),
        )

    async def create_summary_for_electrical(self, tender_id: UUID) -> str:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(tender.category, tender.quarter)
        tender_file: Path | None = manager.path / "tender.xlsx"
        if not tender_file:
            raise FileNotFoundError("招标文件不存在")
        summary_file: Path = manager.create_summary_file_path()

        # 遍历文件系统，按供应商名分组
        bid_files = manager.list_bid_document_files()
        bidders_dict = {}
        for file_path in bid_files:
            name = file_path.stem
            if name.endswith(".bargaining"):
                supplier = name[: -len(".bargaining")]
                if supplier not in bidders_dict:
                    bidders_dict[supplier] = {
                        "document": None,
                        "bargaining_document": None,
                    }
                bidders_dict[supplier]["bargaining_document"] = file_path
            else:
                supplier = name
                if supplier not in bidders_dict:
                    bidders_dict[supplier] = {
                        "document": None,
                        "bargaining_document": None,
                    }
                bidders_dict[supplier]["document"] = file_path

        bidders = []
        for name, files in bidders_dict.items():
            if files["document"] is not None:
                bidders.append(
                    Bidder(
                        name=name,
                        document=files["document"],
                        has_bargaining=files["bargaining_document"] is not None,
                        bargaining_document=files["bargaining_document"],
                    )
                )

        consolidator = ElectricalConsolidator(tender_file, summary_file)
        consolidator.load_tender()
        try:
            consolidator.add_bids(bidders)
        except Exception as e:
            raise e
        consolidator.save()
        supplier_names = [b.name for b in bidders]
        return f"已汇总完成，共计{len(supplier_names)}个供应商：{','.join(supplier_names)}。 + error info"
